# -*- coding: UTF-8 -*-
from django.contrib.auth.models import Group
from django.utils import timezone

from sql.utils.resource_group import user_groups, auth_group_users
from sql.utils.sql_review import is_auto_review
from common.utils.const import WorkflowDict
from sql.models import (
    WorkflowAudit,
    WorkflowAuditDetail,
    WorkflowAuditSetting,
    WorkflowLog,
    ResourceGroup,
    SqlWorkflow,
    QueryPrivilegesApply,
    Users,
    ArchiveConfig,
)
from common.config import SysConfig


class Audit(object):
    # 新增工单审核
    @staticmethod
    def add(workflow_type, workflow_id):
        result = {"status": 0, "msg": "", "data": []}

        # 检查是否已存在待审核数据
        workflow_info = WorkflowAudit.objects.filter(
            workflow_type=workflow_type,
            workflow_id=workflow_id,
            current_status=WorkflowDict.workflow_status["audit_wait"],
        )
        if len(workflow_info) >= 1:
            result["msg"] = "该工单当前状态为待审核，请勿重复提交"
            raise Exception(result["msg"])

        # 获取工单信息
        if workflow_type == WorkflowDict.workflow_type["query"]:
            workflow_detail = QueryPrivilegesApply.objects.get(apply_id=workflow_id)
            workflow_title = workflow_detail.title
            group_id = workflow_detail.group_id
            group_name = workflow_detail.group_name
            create_user = workflow_detail.user_name
            create_user_display = workflow_detail.user_display
            audit_auth_groups = workflow_detail.audit_auth_groups
            workflow_remark = ""
        elif workflow_type == WorkflowDict.workflow_type["sqlreview"]:
            workflow_detail = SqlWorkflow.objects.get(pk=workflow_id)
            workflow_title = workflow_detail.workflow_name
            group_id = workflow_detail.group_id
            group_name = workflow_detail.group_name
            create_user = workflow_detail.engineer
            create_user_display = workflow_detail.engineer_display
            audit_auth_groups = workflow_detail.audit_auth_groups
            workflow_remark = ""
        elif workflow_type == WorkflowDict.workflow_type["archive"]:
            workflow_detail = ArchiveConfig.objects.get(pk=workflow_id)
            workflow_title = workflow_detail.title
            group_id = workflow_detail.resource_group.group_id
            group_name = workflow_detail.resource_group.group_name
            create_user = workflow_detail.user_name
            create_user_display = workflow_detail.user_display
            audit_auth_groups = workflow_detail.audit_auth_groups
            workflow_remark = ""
        else:
            result["msg"] = "工单类型不存在"
            raise Exception(result["msg"])

        # 校验是否配置审批流程
        if audit_auth_groups == "":
            result["msg"] = "审批流程不能为空，请先配置审批流程"
            raise Exception(result["msg"])
        else:
            audit_auth_groups_list = audit_auth_groups.split(",")

        # 判断是否无需审核,并且修改审批人为空
        if SysConfig().get("auto_review", False):
            if workflow_type == WorkflowDict.workflow_type["sqlreview"]:
                if is_auto_review(workflow_id):
                    sql_workflow = SqlWorkflow.objects.get(id=int(workflow_id))
                    sql_workflow.audit_auth_groups = "无需审批"
                    sql_workflow.status = "workflow_review_pass"
                    sql_workflow.save()
                    audit_auth_groups_list = None

        # 无审核配置则无需审核，直接通过
        if audit_auth_groups_list is None:
            # 向审核主表插入审核通过的数据
            audit_detail = WorkflowAudit()
            audit_detail.group_id = group_id
            audit_detail.group_name = group_name
            audit_detail.workflow_id = workflow_id
            audit_detail.workflow_type = workflow_type
            audit_detail.workflow_title = workflow_title
            audit_detail.workflow_remark = workflow_remark
            audit_detail.audit_auth_groups = ""
            audit_detail.current_audit = "-1"
            audit_detail.next_audit = "-1"
            audit_detail.current_status = WorkflowDict.workflow_status[
                "audit_success"
            ]  # 审核通过
            audit_detail.create_user = create_user
            audit_detail.create_user_display = create_user_display
            audit_detail.save()
            result["data"] = {
                "workflow_status": WorkflowDict.workflow_status["audit_success"]
            }
            result["msg"] = "无审核配置，直接审核通过"
            # 增加工单日志
            Audit.add_log(
                audit_id=audit_detail.audit_id,
                operation_type=0,
                operation_type_desc="提交",
                operation_info="无需审批，系统直接审核通过",
                operator=audit_detail.create_user,
                operator_display=audit_detail.create_user_display,
            )
        else:
            # 向审核主表插入待审核数据
            audit_detail = WorkflowAudit()
            audit_detail.group_id = group_id
            audit_detail.group_name = group_name
            audit_detail.workflow_id = workflow_id
            audit_detail.workflow_type = workflow_type
            audit_detail.workflow_title = workflow_title
            audit_detail.workflow_remark = workflow_remark
            audit_detail.audit_auth_groups = ",".join(audit_auth_groups_list)
            audit_detail.current_audit = audit_auth_groups_list[0]
            # 判断有无下级审核
            if len(audit_auth_groups_list) == 1:
                audit_detail.next_audit = "-1"
            else:
                audit_detail.next_audit = audit_auth_groups_list[1]

            audit_detail.current_status = WorkflowDict.workflow_status["audit_wait"]
            audit_detail.create_user = create_user
            audit_detail.create_user_display = create_user_display
            audit_detail.save()
            result["data"] = {
                "workflow_status": WorkflowDict.workflow_status["audit_wait"]
            }
            # 增加工单日志
            audit_auth_group, current_audit_auth_group = Audit.review_info(
                workflow_id, workflow_type
            )
            Audit.add_log(
                audit_id=audit_detail.audit_id,
                operation_type=0,
                operation_type_desc="提交",
                operation_info="等待审批，审批流程：{}".format(audit_auth_group),
                operator=audit_detail.create_user,
                operator_display=audit_detail.create_user_display,
            )
        # 增加审核id
        result["data"]["audit_id"] = audit_detail.audit_id
        # 返回添加结果
        return result

    # 工单审核
    @staticmethod
    def audit(audit_id, audit_status, audit_user, audit_remark):
        result = {"status": 0, "msg": "ok", "data": 0}
        audit_detail = WorkflowAudit.objects.get(audit_id=audit_id)

        # 不同审核状态
        if audit_status == WorkflowDict.workflow_status["audit_success"]:
            # 判断当前工单是否为待审核状态
            if (
                audit_detail.current_status
                != WorkflowDict.workflow_status["audit_wait"]
            ):
                result["msg"] = "工单不是待审核状态，请返回刷新"
                raise Exception(result["msg"])

            # 判断是否还有下一级审核
            if audit_detail.next_audit == "-1":
                # 更新主表审核状态为审核通过
                audit_result = WorkflowAudit()
                audit_result.audit_id = audit_id
                audit_result.current_audit = "-1"
                audit_result.current_status = WorkflowDict.workflow_status[
                    "audit_success"
                ]
                audit_result.save(update_fields=["current_audit", "current_status"])
            else:
                # 更新主表审核下级审核组和当前审核组
                audit_result = WorkflowAudit()
                audit_result.audit_id = audit_id
                audit_result.current_status = WorkflowDict.workflow_status["audit_wait"]
                audit_result.current_audit = audit_detail.next_audit
                # 判断后续是否还有下下一级审核组
                audit_auth_groups_list = audit_detail.audit_auth_groups.split(",")
                for index, auth_group in enumerate(audit_auth_groups_list):
                    if auth_group == audit_detail.next_audit:
                        # 无下下级审核组
                        if index == len(audit_auth_groups_list) - 1:
                            audit_result.next_audit = "-1"
                            break
                        # 存在下下级审核组
                        else:
                            audit_result.next_audit = audit_auth_groups_list[index + 1]
                audit_result.save(
                    update_fields=["current_audit", "next_audit", "current_status"]
                )

            # 插入审核明细数据
            audit_detail_result = WorkflowAuditDetail()
            audit_detail_result.audit_id = audit_id
            audit_detail_result.audit_user = audit_user
            audit_detail_result.audit_status = WorkflowDict.workflow_status[
                "audit_success"
            ]
            audit_detail_result.audit_time = timezone.now()
            audit_detail_result.remark = audit_remark
            audit_detail_result.save()
            # 增加工单日志
            audit_auth_group, current_audit_auth_group = Audit.review_info(
                audit_detail.workflow_id, audit_detail.workflow_type
            )
            Audit.add_log(
                audit_id=audit_id,
                operation_type=1,
                operation_type_desc="审批通过",
                operation_info="审批备注：{}，下级审批：{}".format(
                    audit_remark, current_audit_auth_group
                ),
                operator=audit_user,
                operator_display=Users.objects.get(username=audit_user).display,
            )
        elif audit_status == WorkflowDict.workflow_status["audit_reject"]:
            # 判断当前工单是否为待审核状态
            if (
                audit_detail.current_status
                != WorkflowDict.workflow_status["audit_wait"]
            ):
                result["msg"] = "工单不是待审核状态，请返回刷新"
                raise Exception(result["msg"])

            # 更新主表审核状态
            audit_result = WorkflowAudit()
            audit_result.audit_id = audit_id
            audit_result.current_audit = "-1"
            audit_result.next_audit = "-1"
            audit_result.current_status = WorkflowDict.workflow_status["audit_reject"]
            audit_result.save(
                update_fields=["current_audit", "next_audit", "current_status"]
            )

            # 插入审核明细数据
            audit_detail_result = WorkflowAuditDetail()
            audit_detail_result.audit_id = audit_id
            audit_detail_result.audit_user = audit_user
            audit_detail_result.audit_status = WorkflowDict.workflow_status[
                "audit_reject"
            ]
            audit_detail_result.audit_time = timezone.now()
            audit_detail_result.remark = audit_remark
            audit_detail_result.save()
            # 增加工单日志
            Audit.add_log(
                audit_id=audit_id,
                operation_type=2,
                operation_type_desc="审批不通过",
                operation_info="审批备注：{}".format(audit_remark),
                operator=audit_user,
                operator_display=Users.objects.get(username=audit_user).display,
            )
        elif audit_status == WorkflowDict.workflow_status["audit_abort"]:
            # 判断当前工单是否为待审核/审核通过状态
            if (
                audit_detail.current_status
                != WorkflowDict.workflow_status["audit_wait"]
                and audit_detail.current_status
                != WorkflowDict.workflow_status["audit_success"]
            ):
                result["msg"] = "工单不是待审核态/审核通过状态，请返回刷新"
                raise Exception(result["msg"])

            # 更新主表审核状态
            audit_result = WorkflowAudit()
            audit_result.audit_id = audit_id
            audit_result.next_audit = "-1"
            audit_result.current_status = WorkflowDict.workflow_status["audit_abort"]
            audit_result.save(update_fields=["current_status", "next_audit"])

            # 插入审核明细数据
            audit_detail_result = WorkflowAuditDetail()
            audit_detail_result.audit_id = audit_id
            audit_detail_result.audit_user = audit_user
            audit_detail_result.audit_status = WorkflowDict.workflow_status[
                "audit_abort"
            ]
            audit_detail_result.audit_time = timezone.now()
            audit_detail_result.remark = audit_remark
            audit_detail_result.save()

            # 增加工单日志
            Audit.add_log(
                audit_id=audit_id,
                operation_type=3,
                operation_type_desc="审批取消",
                operation_info="取消原因：{}".format(audit_remark),
                operator=audit_user,
                operator_display=Users.objects.get(username=audit_user).display,
            )
        else:
            result["msg"] = "审核异常"
            raise Exception(result["msg"])

        # 返回审核结果
        result["data"] = {"workflow_status": audit_result.current_status}
        return result

    # 获取用户待办工单数量
    @staticmethod
    def todo(user):
        # 先获取用户所在资源组列表
        group_list = user_groups(user)
        group_ids = [group.group_id for group in group_list]
        # 再获取用户所在权限组列表
        if user.is_superuser:
            auth_group_ids = [group.id for group in Group.objects.all()]
        else:
            auth_group_ids = [group.id for group in Group.objects.filter(user=user)]

        return WorkflowAudit.objects.filter(
            current_status=WorkflowDict.workflow_status["audit_wait"],
            group_id__in=group_ids,
            current_audit__in=auth_group_ids,
        ).count()

    # 通过审核id获取审核信息
    @staticmethod
    def detail(audit_id):
        try:
            return WorkflowAudit.objects.get(audit_id=audit_id)
        except Exception:
            return None

    # 通过业务id获取审核信息
    @staticmethod
    def detail_by_workflow_id(workflow_id, workflow_type):
        try:
            return WorkflowAudit.objects.get(
                workflow_id=workflow_id, workflow_type=workflow_type
            )
        except Exception:
            return None

    # 通过组和审核类型，获取审核配置信息
    @staticmethod
    def settings(group_id, workflow_type):
        try:
            return WorkflowAuditSetting.objects.get(
                workflow_type=workflow_type, group_id=group_id
            ).audit_auth_groups
        except Exception:
            return None

    # 修改\添加配置信息
    @staticmethod
    def change_settings(group_id, workflow_type, audit_auth_groups):
        try:
            WorkflowAuditSetting.objects.get(
                workflow_type=workflow_type, group_id=group_id
            )
            WorkflowAuditSetting.objects.filter(
                workflow_type=workflow_type, group_id=group_id
            ).update(audit_auth_groups=audit_auth_groups)
        except Exception:
            inset = WorkflowAuditSetting()
            inset.group_id = group_id
            inset.group_name = ResourceGroup.objects.get(group_id=group_id).group_name
            inset.audit_auth_groups = audit_auth_groups
            inset.workflow_type = workflow_type
            inset.save()

    # 判断用户当前是否是可审核
    @staticmethod
    def can_review(user, workflow_id, workflow_type):
        audit_info = WorkflowAudit.objects.get(
            workflow_id=workflow_id, workflow_type=workflow_type
        )
        group_id = audit_info.group_id
        result = False
        # 只有待审核状态数据才可以审核
        if audit_info.current_status == WorkflowDict.workflow_status["audit_wait"]:
            try:
                auth_group_id = Audit.detail_by_workflow_id(
                    workflow_id, workflow_type
                ).current_audit
                audit_auth_group = Group.objects.get(id=auth_group_id).name
            except Exception:
                raise Exception("当前审批auth_group_id不存在，请检查并清洗历史数据")
            if (
                auth_group_users([audit_auth_group], group_id)
                .filter(id=user.id)
                .exists()
                or user.is_superuser == 1
            ):
                if workflow_type == 1:
                    if user.has_perm("sql.query_review"):
                        result = True
                elif workflow_type == 2:
                    if user.has_perm("sql.sql_review"):
                        result = True
                elif workflow_type == 3:
                    if user.has_perm("sql.archive_review"):
                        result = True
        return result

    # 获取当前工单审批流程和当前审核组
    @staticmethod
    def review_info(workflow_id, workflow_type):
        audit_info = WorkflowAudit.objects.get(
            workflow_id=workflow_id, workflow_type=workflow_type
        )
        if audit_info.audit_auth_groups == "":
            audit_auth_group = "无需审批"
        else:
            try:
                audit_auth_group = "->".join(
                    [
                        Group.objects.get(id=auth_group_id).name
                        for auth_group_id in audit_info.audit_auth_groups.split(",")
                    ]
                )
            except Exception:
                audit_auth_group = audit_info.audit_auth_groups
        if audit_info.current_audit == "-1":
            current_audit_auth_group = None
        else:
            try:
                current_audit_auth_group = Group.objects.get(
                    id=audit_info.current_audit
                ).name
            except Exception:
                current_audit_auth_group = audit_info.current_audit
        return audit_auth_group, current_audit_auth_group

    # 新增工单日志
    @staticmethod
    def add_log(
        audit_id,
        operation_type,
        operation_type_desc,
        operation_info,
        operator,
        operator_display,
    ):
        WorkflowLog(
            audit_id=audit_id,
            operation_type=operation_type,
            operation_type_desc=operation_type_desc,
            operation_info=operation_info,
            operator=operator,
            operator_display=operator_display,
        ).save()

    # 获取工单日志
    @staticmethod
    def logs(audit_id):
        return WorkflowLog.objects.filter(audit_id=audit_id)
